﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Security.Cryptography;
using System.IO;
using System.Reflection;
using System.Xml.Linq;

using Stp.Core;
using Stp.Data;
using Stp.Test.Fakes;

namespace Stp.Test
{
    [TestClass]
    public class AccountTest
    {
        private FakeCoreRegistry _fCoreReg;
        private FakeEmailAgent _fEmailAgent;

        [TestInitialize]
        public void Setup()
        {
            _fCoreReg = new FakeCoreRegistry();
            _fEmailAgent = new FakeEmailAgent();

            _fCoreReg._currentPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            
            DatalayerInfo dInfo = new DatalayerInfo();
            dInfo.AssemblyName = XElement.Load("Plugins.xml").Element("Datalayer").Element("Assembly").Value;
            dInfo.DefaultNamespace = XElement.Load("Plugins.xml").Element("Datalayer").Element("Namespace").Value;
            
            _fCoreReg._dataLayerInfo = dInfo;
        }

        [TestMethod]
        public void AccountTest_VerifyDataTest()
        {
            AccountModel aModel = new AccountModel();
            aModel.Email = "invalid email";
            aModel.Country = "invalid country";

            Account acct = new Account(aModel, _fCoreReg, _fEmailAgent);
            _fCoreReg._findCountryName = false;
            
            Assert.IsFalse(acct.VerifyData());

            aModel.Email = "test@test.com";
            Assert.IsFalse(acct.VerifyData());

            aModel.Email = "invalid email";
            aModel.Country = "new zealand";
            _fCoreReg._findCountryName = true;
            Assert.IsFalse(acct.VerifyData());

            aModel.Email = "test@test.com";
            aModel.Country = "new zealand";
            Assert.IsTrue(acct.VerifyData());
        }

        [TestMethod]
        public void AccountTest_RegisterTest()
        {
            AccountModel aModel = new AccountModel();
            aModel.Email = "test@test.com";
            aModel.Country = "New Zealand";

            Account acct = new Account(aModel, _fCoreReg, _fEmailAgent);
            _fCoreReg._findCountryName = true;

            acct.Register();

            Dictionary<string, AccountModel> customerAccounts = Datastore.CustomerAccount;
            Assert.AreEqual("test@test.com", customerAccounts["test@test.com"].Email);
            Assert.AreEqual("New Zealand", customerAccounts["test@test.com"].Country);

            string tempPsw = _fEmailAgent.TempPassword;
            SHA256Managed sha256 = new SHA256Managed();
            byte[] hashedPsw = sha256.ComputeHash(Convert.FromBase64String(tempPsw));
            byte[] savedHashedPsw = customerAccounts["test@test.com"].Password;

            for (int i = 0; i < hashedPsw.Length; i++)
            {
                Assert.AreEqual(hashedPsw[i], savedHashedPsw[i]);
            }

            Assert.AreEqual("test@test.com", _fEmailAgent.RegisteredEmailAddress);
            Assert.AreEqual(DateTime.Now.ToShortDateString(), customerAccounts["test@test.com"].DateCreated);
            Assert.AreEqual("Registered", customerAccounts["test@test.com"].Status);
        }

        [TestMethod]
        public void AccountTest_LoginTest()
        {
            AccountModel aModel = new AccountModel();
            aModel.Country = "NEW ZEALAND";
            aModel.DateCreated = DateTime.Now.ToShortDateString();
            aModel.Email = "AccountTest_LoginTest@test.com";

            SHA256Managed sha256 = new SHA256Managed();
            string testPsw = "testpassword";
            byte[] pswHash = sha256.ComputeHash(Convert.FromBase64String(testPsw));
            aModel.Password = pswHash;
            aModel.Status = "Offline";

            Datastore.CustomerAccount.Add("AccountTest_LoginTest@test.com", aModel);

            AccountModel testAcModel = new AccountModel();
            testAcModel.Email = "invalid email address";

            Account insAccount = new Account(testAcModel, _fCoreReg, _fEmailAgent);
            Assert.IsFalse(insAccount.Login());

            testAcModel.Email = "AccountTest_LoginTest@test.com";
            string wrongTestPsw = "wrongtstpassword";
            byte[] wrongPswHash = sha256.ComputeHash(Convert.FromBase64String(wrongTestPsw));
            testAcModel.Password = wrongPswHash;
            Assert.IsFalse(insAccount.Login());

            testAcModel.Password = pswHash;
            Assert.IsTrue(insAccount.Login());
            Assert.AreEqual("Online", Datastore.CustomerAccount["AccountTest_LoginTest@test.com"].Status);
        }

        [TestMethod]
        public void AccountTest_LogoutTest()
        {
            AccountModel aModel = new AccountModel();
            aModel.Country = "NEW ZEALAND";
            aModel.DateCreated = DateTime.Now.ToShortDateString();
            aModel.Email = "AccountTest_LogoutTest@test.com";

            SHA256Managed sha256 = new SHA256Managed();
            string testPsw = "testpassword";
            byte[] pswHash = sha256.ComputeHash(Convert.FromBase64String(testPsw));
            aModel.Password = pswHash;
            aModel.Status = "Online";

            Datastore.CustomerAccount.Add("AccountTest_LogoutTest@test.com", aModel);

            AccountModel testAcModel = new AccountModel();
            testAcModel.Email = "AccountTest_LogoutTest@test.com";
            Account insAccount = new Account(testAcModel, _fCoreReg, _fEmailAgent);
            insAccount.Logout();
            Assert.AreEqual("Offline", Datastore.CustomerAccount["AccountTest_LogoutTest@test.com"].Status);
        }
    }
}
